package com.xtravel.common.widget;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Environment;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import com.xtravel.R;
import com.xtravel.common.helper.EncryptHelper;
import com.xtravel.common.widget.gestureimage.GestureImageView;


import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

public class AsyncGestureImageView extends GestureImageView {
    private static final int DANGER_SIZE = 20;
    private static HashMap<String, Bitmap> bitmapMap = new HashMap<String, Bitmap>();
    private static List<BitmapCache> caches = new ArrayList<BitmapCache>();
    private Context context;
    private View loadingView = null;

    public AsyncGestureImageView(Context context, float minScale, float maxScale) {
        super(context);
        this.context = context;
        this.setMinScale(minScale);
        this.setMaxScale(maxScale);
        this.setScaleType(ImageView.ScaleType.FIT_CENTER);
    }

    public AsyncGestureImageView(Context context, AttributeSet attrs, float minScale, float maxScale) {
        super(context, attrs);
        this.context = context;
        this.setMinScale(minScale);
        this.setMaxScale(maxScale);
        this.setScaleType(ImageView.ScaleType.FIT_CENTER);
    }

    public AsyncGestureImageView(Context context, AttributeSet attrs, int defStyle, float minScale, float maxScale) {
        super(context, attrs, defStyle);
        this.context = context;
        this.setMinScale(minScale);
        this.setMaxScale(maxScale);
        this.setScaleType(ImageView.ScaleType.FIT_CENTER);
    }

    public void setImageUrl(String url) {
        if (loadingView != null) {
            loadingView.setVisibility(VISIBLE);
        }

        new AsyncLoadImageTask(this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, url);
    }

    public void setBitmap(Bitmap bitmap) {
        try {
            this.setImageBitmap(bitmap);

            if (loadingView != null) {
                loadingView.setVisibility(GONE);
            }
        } catch (Exception e) {

        }

    }

    public String getLocalFilePath(String url) {
        try {
            File dirPath = Environment.getExternalStorageDirectory();
            String dir = dirPath.toString() + "/xtravel/cache/images";
            dirPath = new File(dir);
            if (!dirPath.exists()) {
                dirPath.mkdirs();
            }
            String filePath = dirPath.toString() + "/" + EncryptHelper.getMd5String(url) + "_origin";
            return filePath;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public void saveBitmap(Bitmap bitmap, String filePath) throws IOException {
        File file = new File(filePath);
        FileOutputStream out;
        try {
            file.createNewFile();
            out = new FileOutputStream(file);
            if (bitmap.compress(Bitmap.CompressFormat.PNG, 70, out)) {
                out.flush();
                out.close();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private Bitmap getBitmap(String url) {
        if (bitmapMap.containsKey(url)) {
            return bitmapMap.get(url);
        }

        return null;
    }

    private void addBitmapCache(String url, Bitmap bitmap) {
        if (caches.size() >= DANGER_SIZE) {
            int size = caches.size();
            for (int i = size - 1; i >= DANGER_SIZE - 1; i--) {
                BitmapCache cache = caches.get(i);
                bitmapMap.remove(cache.url);
                caches.remove(i);
            }
        }

        BitmapCache cache = new BitmapCache();
        cache.url = url;
        cache.bitmap = bitmap;
        cache.createdTime = new Date().getTime();

        caches.add(cache);
        bitmapMap.put(url, bitmap);
    }

    public void setLoadingView(View loadingView) {
        this.loadingView = loadingView;
        this.loadingView.setVisibility(GONE);
    }

    public class BitmapCache {
        public String url;
        public Bitmap bitmap;
        public Long createdTime;
    }

    public class AsyncLoadImageTask extends AsyncTask<String, Integer, Bitmap> {
        private ImageView imgView;
        private Boolean hasCache = false;

        public AsyncLoadImageTask(ImageView view) {
            imgView = view;
        }

        @Override
        protected Bitmap doInBackground(String... args) {
            String url = args[0];
            Bitmap bitmap = getBitmap(url);

            hasCache = bitmap != null;
            if (!hasCache) {
                String localFilePath = getLocalFilePath(url);

                if (localFilePath != null) {
                    File file = new File(localFilePath);
                    if (file.exists()) {
                        bitmap = BitmapFactory.decodeFile(localFilePath);
                        addBitmapCache(url, bitmap);
                        return bitmap;
                    }
                }

                try {
                    URL myFileUrl = new URL(args[0]);
                    HttpURLConnection conn = (HttpURLConnection) myFileUrl.openConnection();
                    conn.setConnectTimeout(6000);
                    conn.setDoInput(true);
                    conn.setUseCaches(false);
                    if (conn.getResponseCode() == 200) {
                        InputStream is = conn.getInputStream();
                        bitmap = BitmapFactory.decodeStream(is);
                        is.close();

                        saveBitmap(bitmap, localFilePath);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }

                addBitmapCache(url, bitmap);
            }

            return getBitmap(url);
        }

        @Override
        protected void onPostExecute(Bitmap result) {
            if (loadingView != null) {
                loadingView.setVisibility(GONE);
            }

            if (imgView != null && result != null) {
                imgView.setImageBitmap(result);

                if (!hasCache) {
                    imgView.startAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.fade_in));
                }
            }

            super.onPostExecute(result);
        }
    }
}
